STM32+W5500网络通信

您所在的位置:网站首页 tcpip报文透传 w5500 STM32+W5500网络通信

STM32+W5500网络通信

2024-07-10 15:58| 来源: 网络整理| 查看: 265

这里写目录标题 1. W5500模块实现数据通信1. 基本原理2. 程序实现 2. DHCP自动获取IP1. 基本原理2. 程序实现 3. modbus协议1. 基本原理2. 实现过程 4. STM32+W5500实现web服务1. 基本原理2. 程序实现 5. 总结参考

1. W5500模块实现数据通信 引脚初始化,此连线方式用于三个模块功能的整体实现 在这里插入图片描述 PA3 -> W5500_RSTPA4 -> W5500_SCSPA5 -> W5500_SCKPA6 -> W5500_MISOPA7 -> W5500_MOSI 1. 基本原理 基本介绍 Niren_W5500模块是一款基于WIZnet W5500芯片的以太网模块,是泥人电子继 Niren_W5100模块后设计的一块性能更好、性价比更高的以太网模块。模块集成硬件化TCP/IP协议:内部32K字节存储器作TX/RX缓存:支持10/100Mbps的传输速率;支持8个独立端口同时运行;同时模块还支持3.3V或5V电源供电,5V供电时还可以输出3.3V电源,方便用户在不同的单片机系统中使用;模块与单片机系统的通讯方式是简单、方便的SPI通信。 实现思路 W5500内部是硬件TCP/IP协议栈,对外(MCU)只是提供了操作socket的能力,内部支持8个独立的socket,每一个socket通过Socket n寄存器区控制(0≤n≤7)。所以在编写基于Socket的网络应用程序时,可以按照查询Socket状态寄存器实现一个状态机的思路来实现。 2. 程序实现 修改main.c函数 修改为根据本机ip的实际地址 在这里插入图片描述 可修改以太网本地ip地址,实现网络的整体搭建链接 在这里插入图片描述 实验过程中使用固定ip,后改回默认 SPI void SPI_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1 | RCC_APB2Periph_AFIO, ENABLE); /* 初始化SCK、MISO、MOSI引脚 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7); /* 初始化CS引脚 */ GPIO_InitStructure.GPIO_Pin = W5500_SCS; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_Init(W5500_SCS_PORT, &GPIO_InitStructure); GPIO_SetBits(W5500_SCS_PORT, W5500_SCS); /* 初始化配置STM32 SPI1 */ SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex; //SPI设置为双线双向全双工 SPI_InitStructure.SPI_Mode=SPI_Mode_Master; //设置为主SPI SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b; //SPI发送接收8位帧结构 SPI_InitStructure.SPI_CPOL=SPI_CPOL_Low; //时钟悬空低 SPI_InitStructure.SPI_CPHA=SPI_CPHA_1Edge; //数据捕获于第1个时钟沿 SPI_InitStructure.SPI_NSS=SPI_NSS_Soft; //NSS由外部管脚管理 SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_2; //波特率预分频值为2 SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB; //数据传输从MSB位开始 SPI_InitStructure.SPI_CRCPolynomial=7; //CRC多项式为7 SPI_Init(SPI1,&SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPI1寄存器 SPI_Cmd(SPI1,ENABLE); //STM32使能SPI1 }

程序运行,关闭虚拟端口,同时启动调试工具 在这里插入图片描述 修改默认ip,并连接网线,连接到设定网络,启动服务,测试tcp通信

创建链接 在这里插入图片描述启动服务器 在这里插入图片描述 2. DHCP自动获取IP 1. 基本原理 DHCP基本定义 DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)。是一个局域网的网络协议,使用UDP协议工作。 DHCP主要有两个用途: 给内部网络或网络服务供应商自动分配IP地址给用户或者内部网络管理员作为对所有计算机作中央管理的手段。 分配方式 自动分配方式 DHCP服务器为主机指定一个永久性的IP地址,一旦DHCP客户端第一次成功从DHCP服务器端租用到IP地址后,就可以永久性的使用该地址。动态分配方式 DHCP服务器给主机指定一个具有时间限制的IP地址,时间到期或主机明确表示放弃该地址时,该地址可以被其他主机使用。手工分配方式(Manual Allocation),客户端的IP地址是由网络管理员指定的,DHCP服务器只是将指定的IP地址告诉客户端主机。 ip获取 在这里插入图片描述 寻找DHCP服务器分配IP地址接受IP地址IP地址分配确认获取到IP后广播ARP 2. 程序实现 device.c函数配置地址 void set_network(void) { uint8 ip[4]; setSHAR(ConfigMsg.mac);/*配置Mac地址*/ setSUBR(ConfigMsg.sub);/*配置子网掩码*/ setGAR(ConfigMsg.gw);/*配置默认网关*/ setSIPR(ConfigMsg.lip);/*配置Ip地址*/ //Init. TX & RX Memory size of w5500 sysinit(txsize, rxsize); /*初始化8个socket*/ setRTR(2000);/*设置溢出时间值*/ setRCR(3);/*设置最大重新发送次数*/ getSIPR (ip); printf("IP : %d.%d.%d.%d\r\n", ip[0],ip[1],ip[2],ip[3]); getSUBR(ip); printf("SN : %d.%d.%d.%d\r\n", ip[0],ip[1],ip[2],ip[3]); getGAR(ip); printf("GW : %d.%d.%d.%d\r\n", ip[0],ip[1],ip[2],ip[3]); }

默认ip地址 在这里插入图片描述

lip:本机地址sub: 子网掩码gw: 默认网关 程序运行 构建生成hex文件,烧录 在这里插入图片描述断电,boot0置0后,启动串口调试程序,使串口函数可以正常使用 在这里插入图片描述 3. modbus协议 1. 基本原理 定义 Modbus是Modicon(施耐德)公司于1979年开发的串行通信协议。它最初设计用于公司的可编程逻辑控制器(PLC)。 Modbus是一种开放式协议 公开发表并且无著作权要求;易于部署和维护;对供应商来说,修改移动本地的比特或字节没有很多限制; 版本

Modbus RTU(Remote Terminal Unit 远程终端单元):这种方式常采用RS-485做为物理层,一般利用芯片的串口实现数据报文的收发,报文数据采用二进制数据进行通信。

Modbus ASCII :报文使用 ASCII 字符。ASCII 格式使用纵向冗余校验和。Modbus ASCII 报文由冒号 (":")开始 和换行符 (CR/LF) 结尾构成。

Modbus TCP/IP 或 Modbus TCP :这是一种 Modbus 变体版本,使用 TCP/IP 网络进行通信,通过 502 端口进行连接。报文不需要校验和计算,因为以太网底层已经实现了CRC32 数据完整性校验。

Modbus over TCP/IP 或 Modbus over TCP 或 Modbus RTU/IP :这也是一种 Modbus 变体,与 Modbus TCP 的不同之处在于,与 Modbus RTU 一样,校验和包含在报文中。

Modbus UDP:也有在UDP上传输Modbus报文的,不过需要做错误重传机制,这么干的应该不多。

传输方式 控制器能设置为两种传输模式(ASCII或RTU)中的任何一种在标准的Modbus网络通信。用户选择想要的模式,包括串口通信参数(波特率、校验方式等),在配置每个控制器的时候,在一个Modbus网络上的所有设备都必须选择相同的传输模式和串口参数。 ASCII模式 在这里插入图片描述RTU模式 在这里插入图片描述 modbus表 在这里插入图片描述 在这里插入图片描述 2. 实现过程 思路 实现TCP服务器,这个服务器用于在系统中轮询处理,从W5500获取数据和发送数据给W5500都需要通过这部分来实现。TCP服务器得到数据后,我们需要解析数据,并根据解析的上位数据决定进一步的动作,还需要生成返回信息。这部分对应功能就是Modbus TCP服务器的实现。根据Modbus TCP服务器解析出的Modbus消息,需要决定下一步的动作,这个具体动作根据功能码的不同可能有不同需求,所以我们需要根据具体的要求实现不同功能码的动作。 程序实现 main函数 int main(void) { unsigned char i; /* Initialize STM32F103 */ System_Initialization();//系统配置 SysTick_Init();//启动系统滴答定时器 SysTick /* Config W5500 */ W5500_Configuration();//W5500配置 Delay_ms(200);//延时等待 /* Modbus-TCP Init */ eMBTCPInit(MB_TCP_PORT_USE_DEFAULT); //端口依赖事件模块初始化 Delay_ms(200); //延时等待 /* Enable Modbus-TCP Stack */ eMBEnable();//激活协议栈 printf("\r\nModbus-TCP Start!\r\n"); printf("IP:192.168.1.190\r\n"); while(1) { i=Read_SOCK_1_Byte(0,Sn_SR); //读W5500状态 if(i==0) { do { Delay_ms(100);//延时等待 }while(Socket_Listen(0)==FALSE);//设置“Socket n”为“TCP服务器模式” } else if(i==SOCK_ESTABLISHED) //建立TCP连接 { eMBPoll();//启动modbus侦听 BSP_LED();//线圈控制LED灯 } } }

w5500参数配置

/* W5500 configuration */ void W5500_Configuration() { unsigned char array[6]; GPIO_SetBits(GPIO_W5500_RST_PORT, GPIO_W5500_RST_Pin);//上拉 Delay_ms(100); /*delay 100ms 使用systick 1ms时基的延时*/ //等待以太网链路 while((Read_1_Byte(PHYCFGR)&LINK)==0); /* Waiting for Ethernet Link */ Write_1_Byte(MR, RST);//写入W5500普通寄存器一个字节 Delay_ms(20); /*delay 20ms */ /* Set Gateway IP as: 192.168.1.1 */ array[0]=192; array[1]=168; array[2]=1; array[3]=1; Write_Bytes(GAR, array, 4);//设置网关IP /* Set Subnet Mask as: 255.255.255.0 */ array[0]=255; array[1]=255; array[2]=255; array[3]=0; Write_Bytes(SUBR, array, 4);//设置子网掩码 /* Set MAC Address as: 0x48,0x53,0x00,0x57,0x55,0x00 */ array[0]=0x48; array[1]=0x53; array[2]=0x00; array[3]=0x57; array[4]=0x55; array[5]=0x00; Write_Bytes(SHAR, array, 6);//设置MAC地址 /* Set W5500 IP as: 192.168.1.128 */ array[0]=192; array[1]=168; array[2]=1; array[3]=190; Write_Bytes(SIPR, array, 4);//设置W5500的IP地址 }

在这里插入图片描述 在这里插入图片描述

4. STM32+W5500实现web服务 1. 基本原理 实现概述 STM32 W5500配置入网后,通过DHCP动态获取IP地址,在电脑浏览器地址栏输入这个IP地址,可以获取到一个简单form表单的页面,在表单中输入数据,提交到W5500web服务 在这里插入图片描述 http请求过程 在这里插入图片描述 2. 程序实现 W5500模块内部自己实现了TCP/IP协议,在外部只需要通过他提供的接口把相关的参数传递进去就行了,物理地址,本机IP,本机端口,目标端口,目标IP STM32F103C8芯片SPI初始化 void SPI1_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1 | RCC_APB2Periph_AFIO, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; // SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;// SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI1, &SPI_InitStructure); SPI_Cmd(SPI1, ENABLE); //ʹÄÜSPIÍâÉè } void SPI1_SetSpeed(u8 SPI_BaudRatePrescaler) { assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler)); SPI1->CR1&=0XFFC7; SPI1->CR1|=SPI_BaudRatePrescaler; SPI_Cmd(SPI1,ENABLE); } w5500模块主要参数 #ifdef __DEF_IINCHIP_PPP__ #include "md5.h" #endif static uint8 I_STATUS[MAX_SOCK_NUM]; static uint16 SSIZE[MAX_SOCK_NUM]; /**< Max Tx buffer size by each channel */ static uint16 RSIZE[MAX_SOCK_NUM]; /**< Max Rx buffer size by each channel */ uint8 getISR(uint8 s) { return I_STATUS[s]; } void putISR(uint8 s, uint8 val) { I_STATUS[s] = val; } uint16 getIINCHIP_RxMAX(uint8 s) { return RSIZE[s]; } uint16 getIINCHIP_TxMAX(uint8 s) { return SSIZE[s]; } void IINCHIP_CSoff(void) { WIZ_CS(LOW); } void IINCHIP_CSon(void) { WIZ_CS(HIGH); } u8 IINCHIP_SpiSendData(uint8 dat) { return(SPI2_SendByte(dat)); } void IINCHIP_WRITE( uint32 addrbsb, uint8 data) { IINCHIP_ISR_DISABLE(); // Interrupt Service Routine Disable IINCHIP_CSoff(); // CS=0, SPI start IINCHIP_SpiSendData( (addrbsb & 0x00FF0000)>>16);// Address byte 1 IINCHIP_SpiSendData( (addrbsb & 0x0000FF00)>> 8);// Address byte 2 IINCHIP_SpiSendData( (addrbsb & 0x000000F8) + 4); // Data write command and Write data length 1 IINCHIP_SpiSendData(data); // Data write (write 1byte data) IINCHIP_CSon(); // CS=1, SPI end IINCHIP_ISR_ENABLE(); // Interrupt Service Routine Enable } uint8 IINCHIP_READ(uint32 addrbsb) { uint8 data = 0; IINCHIP_ISR_DISABLE(); // Interrupt Service Routine Disable IINCHIP_CSoff(); // CS=0, SPI start IINCHIP_SpiSendData( (addrbsb & 0x00FF0000)>>16);// Address byte 1 IINCHIP_SpiSendData( (addrbsb & 0x0000FF00)>> 8);// Address byte 2 IINCHIP_SpiSendData( (addrbsb & 0x000000F8)) ;// Data read command and Read data length 1 data = IINCHIP_SpiSendData(0x00); // Data read (read 1byte data) IINCHIP_CSon(); // CS=1, SPI end IINCHIP_ISR_ENABLE(); // Interrupt Service Routine Enable return data; } uint16 wiz_write_buf(uint32 addrbsb,uint8* buf,uint16 len) { uint16 idx = 0; if(len == 0) printf("Unexpected2 length 0\r\n"); IINCHIP_ISR_DISABLE(); IINCHIP_CSoff(); // CS=0, SPI start IINCHIP_SpiSendData( (addrbsb & 0x00FF0000)>>16);// Address byte 1 IINCHIP_SpiSendData( (addrbsb & 0x0000FF00)>> 8);// Address byte 2 IINCHIP_SpiSendData( (addrbsb & 0x000000F8) + 4); // Data write command and Write data length 1 for(idx = 0; idx >16);// Address byte 1 IINCHIP_SpiSendData( (addrbsb & 0x0000FF00)>> 8);// Address byte 2 IINCHIP_SpiSendData( (addrbsb & 0x000000F8)); // Data write command and Write data length 1 for(idx = 0; idx 0) { len = recv(ch, (uint8*)http_request, len); *(((uint8*)http_request)+len) = 0; proc_http(ch, (uint8*)http_request); // request is processed disconnect(ch); } break; case SOCK_CLOSE_WAIT: if ((len = getSn_RX_RSR(ch)) > 0) { //printf("close wait: %d\r\n",len); len = recv(ch, (uint8*)http_request, len); *(((uint8*)http_request)+len) = 0; proc_http(ch, (uint8*)http_request); // request is processed } disconnect(ch); break; case SOCK_CLOSED: socket(ch, Sn_MR_TCP, 80, 0x00); /* reinitialize the socket */ break; default: break; }// end of switch } void JTXD_do_http(void) { uint8 ch=SOCK_HTTP; uint16 len; st_http_request *http_request; memset(rx_buf,0x00,MAX_URI_SIZE); http_request = (st_http_request*)rx_buf; // struct of http request /* http service start */ switch(getSn_SR(ch)) { case SOCK_INIT: listen(ch); break; case SOCK_LISTEN: break; case SOCK_ESTABLISHED: //case SOCK_CLOSE_WAIT: if(getSn_IR(ch) & Sn_IR_CON) { setSn_IR(ch, Sn_IR_CON); } if ((len = getSn_RX_RSR(ch)) > 0) { len = recv(ch, (uint8*)http_request, len); *(((uint8*)http_request)+len) = 0; JTXD_proc_http(ch, (uint8*)http_request); // request is processed disconnect(ch); } break; case SOCK_CLOSE_WAIT: if ((len = getSn_RX_RSR(ch)) > 0) { //printf("close wait: %d\r\n",len); len = recv(ch, (uint8*)http_request, len); *(((uint8*)http_request)+len) = 0; JTXD_proc_http(ch, (uint8*)http_request); // request is processed } disconnect(ch); break; case SOCK_CLOSED: socket(ch, Sn_MR_TCP, 80, 0x00); /* reinitialize the socket */ break; default: break; }// end of switch } 修改默认参数地址 main.c函数 在这里插入图片描述修改flash.c初始默认设置地址 在这里插入图片描述同理修改device.c文件ip地址等 在这里插入图片描述 程序烧录运行 构建生成hex文件,烧录 在这里插入图片描述断电,boot0置0后,启动串口调试程序,使串口函数可以正常使用 在这里插入图片描述连接测试 ping +设定ip地址在这里插入图片描述 启动网页服务器 在这里插入图片描述 5. 总结 本次实验中在对w5500模块操作中,存在较多的问题,在进行DHCP获取ip与web服务器搭建过程中出现问题较多 在使用校园网的局域网络时,因为网络端口限制问题,对于动态获取与ping连接等存在较多问题,同时会出现拒绝访问现象 在这里插入图片描述实验中尽量避免使用端口局限性较多的网络,同时在进行网络数据发送中,需要关闭自虚拟网络端口,否则可能出现网络丢包现象 在进行网络端口访问中,同时应保证网络联通与电压稳定性,在进行DHCP获取ip过程中因线路问题导致电压不稳定,获取ip只能显示部分 参考

STM32F103基于W5500实现modbus简单TCP通信 通讯接口应用笔记3:使用W5500实现Modbus TCP服务器 基于w5500实现TCP/IP协议后应用层开发 基于STM32和W5500的Modbus TCP通讯 DHCP 原理以及IP获取过程 STM32 W5500 HTTP Server 微型web服务实现 通讯接口应用笔记3:使用W5500实现Modbus TCP服务器 Modbus协议最基础概念详细介绍 图文详解Modbus-RTU协议



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3